/* eslint-disable */
import auth0 from "auth0-js"
import { EventEmitter } from "events"
import authConfig from "../auth_config"

const webAuth = new auth0.WebAuth({
    domain: authConfig.domain,
    redirectUri: `${window.location.origin}/callback`,
    clientID: authConfig.clientId,
    responseType: "token id_token",
    scope: "openid profile",
})

const localStorageKey = "loggedIn"
const loginEvent = "loginEvent"

class AuthService extends EventEmitter {
    idToken = null
    profile = null
    tokenExpiry = null
    sub = null

    login() {
        webAuth.authorize()
    }

    logout() {
        localStorage.removeItem(localStorageKey)

        this.idToken = null
        this.tokenExpiry = null
        this.profile = null

        webAuth.logout({
            returnTo: `${window.location.origin}`,
        })

        this.emit(loginEvent, { loggedIn: false })
    }

    handleAuthentication() {
        return new Promise((resolve, reject) => {
            webAuth.parseHash((err, authResult) => {
                console.log("handleAuthentication -> webAuth.parseHash", err, authResult)
                if (err) {
                    reject(err)
                } else {
                    this.localLogin(authResult)
                    resolve(authResult.idToken)
                }
            })
        })
    }

    isAuthenticated() {
        return localStorage.getItem(localStorageKey) === "true"
    }

    getSub() {
        return this.sub
    }

    isIdTokenValid() {
        return this.idToken && this.tokenExpiry && Date.now() < this.tokenExpiry
    }

    getIdToken() {
        return new Promise((resolve, reject) => {
            if (this.isIdTokenValid()) {
                resolve(this.idToken)
            } else if (this.isAuthenticated()) {
                this.renewTokens().then((authResult) => {
                    resolve(authResult.idToken)
                }, reject)
            } else {
                reject()
            }
        })
    }

    localLogin(authResult) {
        this.idToken = authResult.idToken
        this.profile = authResult.idTokenPayload
        this.sub = authResult.sub

        // Convert the expiry time from seconds to milliseconds,
        // required by the Date constructor
        this.tokenExpiry = new Date(this.profile.exp * 1000)

        localStorage.setItem(localStorageKey, "true")
        localStorage.setItem("apollo-token", authResult.idToken)

        this.emit(loginEvent, {
            loggedIn: true,
            profile: authResult.idTokenPayload,
            state: authResult.appState || {},
            sub: authResult.sub,
        })
    }

    renewTokens() {
        return new Promise((resolve, reject) => {
            if (localStorage.getItem(localStorageKey) !== "true") {
                return reject("Not logged in")
            }

            webAuth.checkSession({}, (err, authResult) => {
                if (err) {
                    localStorage.setItem(localStorageKey, "false")
                    localStorage.removeItem("apollo-token")
                    reject(err)
                } else {
                    this.localLogin(authResult)
                    resolve(authResult)
                }
            })
        })
    }
}

const service = new AuthService()
service.setMaxListeners(5)

export default service
export type { AuthService }
